package mobile.game.common.net.netty;


import java.nio.ByteBuffer;
import java.util.concurrent.LinkedBlockingQueue;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import mobile.game.core.config.JowConfig;
import mobile.game.core.support.Utils;
import mobile.game.core.support.log.LogCore;

public class ClientHandler extends ChannelInboundHandlerAdapter {
	
	/**
	 * 通信对象
	 */
	private Channel channel = null;
	
	/** 待处理消息列表*/
	private final LinkedBlockingQueue<byte[]> listInStream = new LinkedBlockingQueue<>();
	
	/** 加密系统*/
	private RC4 rc4 = null;
	
	private boolean firstMsg = false;
	
	@Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		
		channel = ctx.channel();
		
		firstMsg = false;
		
		// 日志
		if(LogCore.conn.isDebugEnabled()) {
			LogCore.conn.debug("连接服务器，本地地址={}, 远程地址={}", 
					channel.localAddress(), channel.remoteAddress());
		}
    }
	
	@Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        
        channel = null;
        
	    // 日志
		if (LogCore.conn.isDebugEnabled()) {
			LogCore.conn.debug("关闭与服务器的连接");
		}
    }
	
	@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		byte[] buf = (byte[])msg;
		
		if (!firstMsg) {
			firstMsg = true;
			
			if(JowConfig.CONN_ENCRYPT){
				int len = Utils.bytesToBigEndian32(buf, 0);
				byte[] msgbuf = new byte[len - 4];
				System.arraycopy(buf, 4, msgbuf, 0, len - 4);
				
				// 生成机密系统
				rc4 = new RC4(msgbuf);
			}
			
			return ;
		}
		
		listInStream.add(buf);
	}
	
	public void sendMsgToServer(int msgId, byte[] buf) {
		//准备数据
		byte[] header = new byte[8];
		Utils.bigEndian32ToBytes(header, 0, buf.length + 8);
		Utils.bigEndian32ToBytes(header, 4, msgId);
		
		ByteBuffer testBuf = ByteBuffer.allocate(buf.length + header.length); 
		testBuf.put(header);
		testBuf.put(buf);
		byte[] buffResult = testBuf.array();
		if(JowConfig.CONN_ENCRYPT && rc4 != null){
			rc4.crypt(buffResult, 4, buffResult.length);
		}
		
		channel.write(buffResult);
		channel.flush();
	}
	
	public void close() {
		channel.close();
	}
}
